<!-- 简易多选结构树 -->

<template>
  <div :class="divClass" :style="divStyle">
    <!-- 顶部插槽 -->
    <div :class="`${className}-top`">
      <slot name="top" />
    </div>

    <!-- 筛选框 -->
    <el-input v-if="!noFilter" v-model.trim="filter" :placeholder="filterTip" clearable>
      <template v-if="filterPrefix" #prefix>
        <i class="el-input__icon" :class="filterPrefix" />
      </template>
      <template v-if="filterSuffix" #suffix>
        <i class="el-input__icon" :class="filterSuffix" />
      </template>
    </el-input>

    <!-- 结构树 -->
    <EasyScroll :wide="wide" hasX>
      <el-tree ref="tree" v-bind="config" @check="nodeCheck" @node-expand="nodeExpand" @node-collapse="nodeCollapse">
        <template #default="{ node, data }">
          <div>
            <slot :data="data" :nodeClass="getNodeClass(data)">
              <span :class="getNodeClass(data)">{{ node.label }}</span>
            </slot>
            <BtnAll v-if="hasAll && !CORE.isEmpty(data[props.children])" v-bind="allBtn" @click="nodeClick({})" />
          </div>
        </template>
      </el-tree>
    </EasyScroll>

    <!-- 底部插槽 -->
    <div :class="`${className}-bottom`">
      <slot name="bottom" />
    </div>
  </div>
</template>

<script>
// ============================== 导入依赖 ============================== //

import CORE from '@/CORE'
import mixPath from '../mixPath'
import UTIL from '../EasyTree/UTIL'
import WebForm from '../WebForm'

const name = 'EasyTreeMulti'

// ============================== 导出组件 ============================== //

export default {
  /**
   * 名称定义 (实际使用名称)
   */
  name,

  /**
   * 混入列表 (配置选项合并)
   */
  mixins: [mixPath],

  /**
   * 组件导入 (Abc.vue + Abc/index.vue)
   */
  ...CORE.components(require.context('./', true, /vue$/)),

  /**
   * 属性注册 (抽取以便查阅)
   */
  props: CORE.WEB[name],

  /**
   * 模型绑定
   */
  model: {
    prop: 'chosenId', // 与 props 里的名称一致
    event: 'idChange', // 回传调用的事件名称
  },

  /**
   * 状态数据 (函数返回对象)
   */
  data() {
    return {
      filter: '', // 过滤值
    }
  },

  /**
   * 计算属性 (慎用箭头函数)
   */
  computed: {
    /**
     * 尺寸
     */
    size: WebForm.computed.size,

    /**
     * 默认 ID 列表
     */
    initIdList() {
      const { tree, state, chosenId, init, namesMap } = this
      if (chosenId) return chosenId // 已有选中
      if (!(tree || state.tree).length) return [] // 结构树为空
      if (init) return init.filter((id) => namesMap[id]) // 只返回存在的 ID 列表
      return [] // 无选中
    },

    /**
     * 属性映射
     */
    props() {
      const { field, state } = this
      const treeField = field || state.TREE_FIELD || []
      const [children = 'children', id = 'id', label = 'name'] = treeField
      return { children, id, label, disabled: 'disabled' }
    },

    /**
     * 表单配置
     */
    config() {
      const { elProps, tree, state, props, expandRoot } = this
      const defaultExpandedKeys = expandRoot ? tree.map((item) => item[props.id]) : null
      return {
        ...elProps,
        data: tree || state.tree,
        nodeKey: props.id,
        props,
        defaultExpandAll: this.expandAll,
        filterNodeMethod: this.filterNode,
        defaultCheckedKeys: this.initIdList,
        defaultExpandedKeys,
        showCheckbox: true,
        checkStrictly: this.noLinkage,
        checkOnClickNode: true,
        expandOnClickNode: this.expandOnClick,
        indent: 30,
      }
    },

    /**
     * 路径名称的映射
     */
    namesMap() {
      const { tree, state, props } = this
      const namesMap = {}
      UTIL.setNamesMap(namesMap, tree || state.tree, props)
      return namesMap
    },

    /**
     * 样式类
     */
    divClass() {
      const { className, size, noPadding } = this
      const sizeStr = size ? ` ${className}-${size}` : ''
      const paddingStr = noPadding ? ` ${className}-no-padding` : ''
      return `${className}${sizeStr}${paddingStr}`
    },

    /**
     * 样式对象
     */
    divStyle() {
      const { height, getSize } = this
      const style = {}
      if (height) style.height = getSize(height)
      return style
    },
  },

  /**
   * 监听属性 (深度 deep 首次 immediate)
   */
  watch: {
    /**
     * 监听默认 ID 列表
     */
    initIdList: {
      immediate: true,
      handler(idList) {
        this.$emit('idChange', idList)
        this.$refs.tree && this.$refs.tree.setCheckedKeys(idList)
      },
    },

    /**
     * 监听过滤值
     */
    filter(val) {
      this.$refs.tree.filter(val)
    },

    /**
     * 监听结构树
     */
    async 'config.data'() {
      await this.$nextTick()
      this.$refs.tree.filter(this.filter)
    },

    /**
     * 监听级联切换
     */
    async noLinkage() {
      if (this.$refs.tree) {
        // 触发联动更新
        this.$refs.tree.setCheckedKeys([])
        await this.$nextTick
        this.$refs.tree.setCheckedKeys(this.initIdList)

        // 重新提交数据
        const idList = this.$refs.tree.getCheckedKeys()
        this.$emit('idChange', idList)
      }
    },
  },

  /**
   * 本地方法 (轻量重要在前)
   */
  methods: {
    /**
     * 节点点击
     */
    nodeClick(data) {
      // if (data.disabled) return

      // const { props } = this
      // this.$emit('idChange', data[props.id])
      // this.$emit('change', data)
    },

    /**
     * 节点选择
     */
    nodeCheck(node, data) {
      if (node.disabled) return

      this.$emit('idChange', data.checkedKeys)
      this.$emit('change', data.checkedNodes)
    },

    /**
     * 节点展开
     */
    nodeExpand(data) {
      this.$emit('expand', data)
    },

    /**
     * 节点收缩
     */
    nodeCollapse(data) {
      this.$emit('collapse', data)
    },

    /**
     * 过滤节点
     */
    filterNode(value, data) {
      if (!value) return true

      const { props, namesMap } = this
      const id = data[props.id]
      return namesMap[id].includes(value)
    },

    /**
     * 获取节点样式类
     */
    getNodeClass(data) {
      const { props, chosenId, className } = this
      if (data.disabled) return `${className}-disabled`
      if (data[props.id] === chosenId) return `${className}-chosen el-button--text`
      return null
    },
  },
}
</script>
